var objSites = new Object();
var version = "0.3.1"
var pollInterval = 1000 * 3600;  // 1 час
var requestTimeout = 1000 * 10;  // 10 секунд
var glb_abortTimerId;

function upgrade () {
  if (localStorage["version"] >= "0.2" ) {
    localStorage["version"] = version;
    localStorage["need_upgrade"] = "false";
    return;
  }
  var confText = "Расширение UNITTCEX обновилось.\n\n";
  confText+="Вообще-то, сейчас должна была бы запуститься процедура обновления конфигурации, ";
  confText+="но програмисты её пока не придумали. Так что мне придётся удалить все ваши настройки, ";
  confText+="а вам - всё настроить заново. Извините. Кстати, вы можете сделать это в другой раз.\n\n";
  confText+="Сделать это прямо сейчас?";

  if (! confirm(confText))
    return;

  console.log("Очищаем objSites.host");
  localStorage["objSites.host"] = "[]";
  localStorage["version"] = version;
  localStorage["need_upgrade"] = "false";
  set_options();
  chrome.tabs.create({url : "options.html"});
}

function init() {
  //var rawSitesData = document.getElementById("template").innerHTML;
  //objSites = xml2json.parser(rawSitesData,"template");
  set_options();

  //Установка обработчика обмена сообщениями
  chrome.extension.onRequest.addListener(requestHandler);

  //Установка обработчика клика по кнопке
  /*chrome.browserAction.onClicked.addListener(function(windowId) {
    onClick();
  });*/

  //Запуск фоновой части скрипта
  glb_abortTimerId = window.setTimeout(startRequest, 0);
}

function set_options() {
  //Настройки
  console.log("Читаю настройки из локального хранилища...");

  //Как часто проверять
  if(localStorage["pollInterval"] != null && !Number(localStorage["pollInterval"]).NaN) {
    pollInterval = Number(localStorage["pollInterval"]);
    if(pollInterval < 3600000)
          pollInterval = 3600000;
    }
  localStorage["lb_pollInterval"] = pollInterval;

  if(localStorage["objSites.host"] != null) {
    try {
      JSON.parse(localStorage["objSites.host"]);
    } catch (e) {
      console.error("objSites.host не в формате JSON. Придётся очистить массив.");
      localStorage["objSites.host"] = "[]";
    }
  } else {
    localStorage["objSites.host"] = "[]";
  }
  objSites.host = JSON.parse(localStorage["objSites.host"]);
  objSites.host.sort(sortByName);

  if(localStorage["version"] == null) {
    localStorage["version"] = version;
    //Если первый запуск, открыть страницу настроек
    chrome.tabs.create({url : "options.html"});
  }

  if (localStorage["version"] == null || localStorage["version"] >= version) {
    localStorage["version"] = version;
  } else {
    localStorage["need_upgrade"] = "true";
  }

  if (localStorage["need_upgrade"] == "true")
    upgrade();

}

//Функция для запуска опроса по расписанию
function scheduleRequest() {
    glb_abortTimerId = window.setTimeout(startRequest, pollInterval);
}

//Функция запроса с применением AJAX
//Почему именно так, не спрашивайте.
//Главное, что работает.
function startRequest() {

  var aSleep = 100;
  var hostsProcessed = 0;
  var hostsCount;

//Функция ожидает, пока все хосты будут обработаны
function verify_sync() {
  if (hostsProcessed < hostsCount) {
    window.setTimeout(verify_sync, aSleep);
    return;
  }

  console.log("По-моему, опрос закончен.");
  updateInfo(true, null, true);
  localStorage["objSites.host"] = JSON.stringify(objSites.host);
  scheduleRequest();
  
}

  hostsCount = objSites.host.length;
  for (var i = 0; i < objSites.host.length; i++) {
    if (objSites.host[i].parm)
    getInfo(objSites.host[i],
    function() {
	hostsProcessed++ ;
        //updateInfo(true, null, true);
	//localStorage["objSites.host"] = JSON.stringify(objSites.host);
        //scheduleRequest();
    },
    function() {
	hostsProcessed++ ;
        //setLoggedOutState();
        //scheduleRequest();
    }, true
    );
  }
  window.setTimeout(verify_sync, aSleep);
}

function getInfo(hObj, onSuccess, onError, allowskip) {
    var xhr = new XMLHttpRequest();
    //внутренний объект
    var iObj;
    //УРЛ запроса
    var tURL;
    //флаг завершения обработки запроса
    var finished = true;
    //пауза
    var sleep_timeout = 1000;
    var short_sleep = 100;
    var aSleep;
    //индекс для массива objSites.host[]
    var k = -1;

    //Функция отмены слишком долгих запросов
    var abortTimerId;
    function setTimeoutHandler(aTimeout) {
      abortTimerId = window.setTimeout(function() {
	  xhr.abort();
	  console.log("Во время обработки "+hObj.name+" "+iObj.name+" возникли проблемы с Интернетом. Я, пожалуй, оставлю старые данные.");
	  finished = true;
      }, aTimeout);
    }

    function clearTimeoutHandler() {
      window.clearTimeout(abortTimerId);
    }

    function handleSuccess(count) {
        //window.clearTimeout(abortTimerId);
	clearTimeoutHandler();
	console.log("local_getInfo успешно завершается!");
        if (onSuccess)
            onSuccess(count);
    }

    function handleError() {
        //window.clearTimeout(abortTimerId);
	clearTimeoutHandler();
        if (onError)
            onError();
	iObj.value = unk;
    }

//Внутрення функция, отвечающая непосредственно за обработку ответа
  function local_getInfo(){
    var regexpArray = new Array();
    //console.log(hObj.name+" xhr.readyState="+xhr.readyState);
    //Если мы таки что-то получили
    if (xhr.readyState == 4 && xhr.status == 200) {
      //Подготовка к парсингу
      var t1 = xhr.responseText;
      var t2 = "";
      if (xhr.responseText) {
      	regexpArray = toArray(iObj.regexp);
	//Применить все регекспы последовательно, при чём каждый следующий - к результату предыдущего
	for (i = 0; i < regexpArray.length; i++) {
	  var tr = unescape(regexpArray[i]);
	  var r = new RegExp(tr, "igm");
	  //t2 = r.exec(t1);
	  t2 = r.exec(unescape(t1));
	  t1=t2
	}
	//Мы что-то нашли! Возможно, даже то, что искали.
	if (t1) {
	  res = t1[t1.length-1]
	  console.log(hObj.name+" "+iObj.name+"="+res);
	  iObj.value = res;
	} else {
	  console.log(hObj.name+" "+iObj.name+": поиск ничего не дал. Возможно, не выполнен вход на трекер.");
	  iObj.value = unk;
	}
      } else {
	console.log("Не получил ответа. Проверьте url: " + tURL);
      }
    }

    //Если запрос завершён, установить соотв. флаг
    if (xhr.readyState == 4)
      finished = true;
  }

  //Функция запускается с паузой, т.к. в Яваскрипте до сих пор нет sleep()
  function local_sleep() {
    try {
      //Если запрос не завершён, ждём ещё
      if (!finished) {
	window.setTimeout(local_sleep, aSleep);
	return;
      }

      //Если мы попали сюда, значит предыдущий запрос завершился
      //или это первый запуск. В любом случае, надо сбросить обработчик таймаута
      clearTimeoutHandler();
      //При изменении статуса запроса вызвать эту функцию
      xhr.onreadystatechange = local_getInfo;

      xhr.onerror = function(error) {
	console.log(error);
	console.log("Ошибка во время обработки "+hObj.name+" "+iObj.name+" xhr.readyState="+xhr.readyState+" xhr.status="+xhr.status);
	handleError();
	finished = true;
	}

      //Запрос

      //При первом запуске получим k=0
      k++;
      //Есть ещё параметры или нет?
      if (k >= hObj.parm.length) {
	handleSuccess();
	return;
      }

      //Таймаут по умолчанию
      aSleep = sleep_timeout;
      //Если есть, кого опросить
      if (hObj.parm[k].url) {
	//Если можно пропускать параметры и установлен соотв. флаг в конфигурации
	if ((allowskip) && (hObj.parm[k].skip == "true")) {
	  ;
	} else {
	  //Работаем
	  finished = false;
	  console.log ("Опрашиваем "+hObj.name+" параметр "+hObj.parm[k].name);
	  //Установка обработчика таймаута
	  setTimeoutHandler(requestTimeout);
	  //Некое подобие кэширования на стороне клиента
	  //Если мы ещё не опрашивали УРЛ, запустить запрос
	  if (tURL != unescape(hObj.parm[k].url) || xhr.readyState != 4) {
	    tURL = unescape(hObj.parm[k].url);
	    iObj = hObj.parm[k];
	    xhr.open("GET", tURL, true);
	    xhr.send(null);
	  } else {
	  //... иначе воспользоваться предыдущими результатами
	    iObj = hObj.parm[k];
	    //console.log("Client side cache hit!");
	    local_getInfo();
	    //Т.к. данные уже готовы, нет смысла ждать долго
	    aSleep = short_sleep;
	  }
	}
      }
    } catch(e) {
      console.error("exception: " + e);
      handleError();
    }

  //Запрос асинхронный, так что можно немного отдохнуть
  window.setTimeout(local_sleep, aSleep);
  }

  //Запуск цикла опроса параметров
  window.setTimeout(local_sleep, 0);
}

//Обработка нажатия на кнопку расширения
function onClick() {
 //startRequest();
}

//Функция обработки сообщений из контент скриптов или расширений
//В request.content содержится как бы команда или как бы описание 
//переданных данных
function requestHandler (request, sender, sendResponse) {
  var aSleep = 100;
  var hostsProcessed = 0;
  var hostsCount;

//Функция ожидает, пока все хосты будут обработаны
function verify_sync() {
  if (request.content != "verify")
    return;
  if (hostsProcessed < hostsCount) {
    window.setTimeout(verify_sync, aSleep);
    return;
  }

  console.log("По-моему, опрос закончен.");
  //Отвечаем
  sendResponse({content: updateInfo(false, request.objSites)});
  
}
  
  console.log(sender.tab ?
                "Нам посылка из контент скрипта:" + Url.decode(sender.tab.url) :
                "Нам посылка из расширения");

  //Обновить настройки
  if (request.content == "reread_options") {
    console.log("Поступила команда обновлить настройки");
    set_options();
    //Перезапустить фоновый опрос трекеров
    window.clearTimeout(glb_abortTimerId);
    glb_abortTimerId = window.setTimeout(startRequest, 0);
  }
  //Опрос трекеров для проверки правильности настроек
  if (request.content == "verify") {
    console.log("Поступила команда на загрузку информации с трекеров для проверки пользователем");
    hostsCount = request.objSites.host.length;
    for (var i = 0; i < request.objSites.host.length; i++) {
      if (request.objSites.host[i].parm)
      getInfo(request.objSites.host[i],
      function() {
	  //Типа синхронизация
	  //Не отвечать, пока не обработаны все хосты
	  hostsProcessed++ ;
	  //Отвечаем
	  //sendResponse({content: updateInfo(false, request.objSites)});
	  //scheduleRequest();
      },
      function() {
	  //Типа синхронизация
	  //Не отвечать, пока не обработаны все хосты
	  hostsProcessed++ ;
	  //setLoggedOutState();
	  //scheduleRequest();
      }
      );
    }
    window.setTimeout(verify_sync, aSleep);
  }
  //Обновить данные немедленно
  if (request.content == "renew_all") {
    console.log("Поступила команда немедленно обновить данные");
    //Перезапустить фоновый опрос трекеров
    window.clearTimeout(glb_abortTimerId);
    glb_abortTimerId = window.setTimeout(startRequest, 0);
  }
}

//Функция обновления результатов.
//Если setTitle == true, установить всплывающую подсказку
function updateInfo(setTitle, loc_objSites, allowskip) {
  var res = "";

  //Если нам не передали объект с хостами, используем наш местный объект
  if (!loc_objSites)
    loc_objSites = objSites;

  for (var i = 0; i < loc_objSites.host.length; i++) {
    res += loc_objSites.host[i].name;
    for (var j = 0; j < loc_objSites.host[i].parm.length; j++) {
      //Пропускать или нет?
      if (allowskip && loc_objSites.host[i].parm[j].skip == "true")
	continue;
      res += " " + getNameOrTxt(loc_objSites.host[i].parm[j]) + getValue(loc_objSites.host[i].parm[j]);
    }

    res += "\n";
  }
  if (setTitle)
    chrome.browserAction.setTitle({title:res});
  return res;
}

document.addEventListener("DOMContentLoaded", function() {
  console.log("Ура! Запуск!");
  init();
});